package edu.neu.cs6515.board.rules;

import edu.neu.cs6515.board.BoardCoord;
import edu.neu.cs6515.board.Hexagon;
import edu.neu.cs6515.board.HexagonBoard;
import edu.neu.cs6515.board.HexagonDirection;
import edu.neu.cs6515.util.Funct;
import edu.neu.cs6515.xml.IngeniousColor;
import edu.neu.cs6515.xml.Placement;

/**
 * Verifies that a place tile is at least adjacent to one other colored hexagon
 * on the board
 */
public final class AdjacentPlacementRule extends Rule {

    public static final String REASON = "NOT-ADJACENT-TO-PREVIOUSLY-PLACED";

    /**
     * Init class with board obj
     * 
     * @param board
     *            the board to be used for validation
     */
    public AdjacentPlacementRule(final HexagonBoard board) {
        super(board);
    }

    @Override
    public boolean validate(final Placement p) {
        final BoardCoord coord0 = p.getBoardCoord0();
        final BoardCoord coord1 = p.getBoardCoord1();
        return hasOccupiedNeighbor(coord0) || hasOccupiedNeighbor(coord1);

    }

    /**
     * check if the Hexagon at given coordinate has an occupied neighbor (non white)
     * 
     * @param coord Boardcoord to check
     * @return true iff at least one of the neighbors of the hexagon is already occupied
     */
    private boolean hasOccupiedNeighbor(final BoardCoord coord) {
        Hexagon hex = board.getHexagons().get(coord);
        for (Funct<Hexagon, Hexagon> funct : HexagonDirection
                .getAllDirections()) {
            Hexagon neighbor = funct.exec(hex);
            if (neighbor != null && neighbor.getColor() != IngeniousColor.WHITE) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String getReason() {
        return REASON;
    }
}
